package com.gzhryc.shared_device.iot.code.services;

import com.gzhryc.common.IDTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.iot.code.dao.IOTServerNodeDao;
import com.gzhryc.shared_device.iot.code.dao.db.IOTServerNode;
import com.gzhryc.shared_device.iot.code.dao.enums.EAliyunLinkType;
import com.gzhryc.shared_device.iot.code.dao.enums.IOTServerNodeEnum;
import com.gzhryc.shared_device.iot.code.services.dto.IOTServerNodeSearch;
import com.gzhryc.shared_device.iot.core.aliyun.models.AliyunIOTConfig;
import com.gzhryc.shared_device.iot.core.enums.EIOTType;
import com.gzhryc.shared_device.iot.core.hryc.models.HRYCIOTConfig;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

public class IOTServerNodeService {

	static Logger log = Logger.getLogger(IOTServerNodeService.class);

	public static IOTServerNodeService self() {
		return MultiDBTools.getService(IOTServerNodeService.class, true);
	}

	public static IOTServerNodeService self(String jdbcKey) {
		return MultiDBTools.getService(jdbcKey, IOTServerNodeService.class, true);
	}

	IOTServerNodeDao dao;

	public IOTServerNodeService(String jdbcKey) {
		this.dao = new IOTServerNodeDao(jdbcKey);
	}

	public List<IOTServerNode> findJoinBySearch(IOTServerNodeSearch search, Integer pageNo, Integer pageLimit) {
		Conditions condition = dao.buildConditions(search);
		condition.and().is("id", search.getId());
		condition.and().likeBoth("name", search.getName());
		condition.and().likeBoth("productKey", search.getProductKey());
		condition.desc("createDate");
		try {
			return dao.findJoinByCondition(condition, pageNo, pageLimit);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public Long countJoinBySearch(IOTServerNodeSearch search) {
		Conditions condition = dao.buildConditions(search);
		try {
			return dao.countJoin(condition);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return 0L;
	}

	public List<IOTServerNode> findAllUnable() {
		Conditions condition = new Conditions(IOTServerNode.class);
		condition.and().is("state", IOTServerNodeEnum.State.Usable.index());
		try {
			return dao.findByCondition(condition);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public IOTServerNode getById(Long id) {
		try {
			return dao.getById(id);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public IOTServerNode getJoinById(Long id) {
		try {
			return dao.getJoinById(id);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public boolean save(IOTServerNode iotServerNode) throws LogicException {
		IOTServerNode temp = getById(iotServerNode.getId());
		if (temp == null) {
			if (IOTServerNodeEnum.State.Usable.index().equals(iotServerNode.getState())) {
				return add(iotServerNode);
			}
		} else {
			if (IOTServerNodeEnum.State.Usable.index().equals(iotServerNode.getState())) {
				return updateNotNull(iotServerNode);
			} else {
				return deleteById(temp.getId());
			}
		}
		return true;
	}

	public boolean add(IOTServerNode iotServerNode) throws LogicException {
		try {
			if(iotServerNode.getId() == null) {
				Long maxId = dao.getMaxId();
				if (maxId == null) {
					maxId = 0L;
				}
				iotServerNode.setId(maxId + 100);
			}
			iotServerNode.setApiToken(IDTools.getUUID());
			iotServerNode.setCreateDate(new Date());
			return dao.insert(iotServerNode) > 0;
		} catch (SQLException e) {
			log.error("新增IOT节点错误", e);
		}
		return false;
	}

	public boolean updateNotNull(IOTServerNode iotServerNode) throws LogicException {
		try {
			if(dao.updateNotNull(iotServerNode) > 0){
				return true;
			}
		} catch (SQLException e) {
			log.error("修改IOT节点错误", e);
		}
		return false;
	}

	public boolean start(Long id) throws LogicException {
		IOTServerNode iotServerNode = getById(id);
		if(iotServerNode == null){
			throw new LogicException("未找到IOT节点信息");
		}
		if(IOTServerNodeEnum.State.Usable.index().equals(iotServerNode)){
			return true;
		}
		if(StringTools.isBlank(iotServerNode.getLinkConfig())){
			throw new LogicException("IOT连接未配置");
		}
		if (EIOTType.ALIYUN.index().equals(iotServerNode.getIotType())) {
			AliyunIOTConfig linkConfig = JsonTools.fromJson(iotServerNode.getLinkConfig(),AliyunIOTConfig.class);
			if(StringTools.isBlank(linkConfig.getRegionId()) || StringTools.isBlank(linkConfig.getAccessKey())
					|| StringTools.isBlank(linkConfig.getAccessSecret())){
				throw new LogicException("阿里云主要配置未填写");
			}
			if(EAliyunLinkType.MNS.index().equals(linkConfig.getLinkType())){
				if(StringTools.isBlank(linkConfig.getAccountEndpoint()) || StringTools.isBlank(linkConfig.getQueueName())
						|| StringTools.isBlank(linkConfig.getUid())){
					throw new LogicException("阿里云MNS配置未填写");
				}
			}
		}else if(EIOTType.HRYC_SMART.index().equals(iotServerNode.getIotType())) {
			HRYCIOTConfig linkConfig =JsonTools.fromJson(iotServerNode.getLinkConfig(), HRYCIOTConfig.class);
			if(StringTools.isBlank(linkConfig.getIp()) || linkConfig.getPort() == null){
				throw new LogicException("物联网主要配置未填写");
			}
		}

		IOTServerNode updateEntity = new IOTServerNode();
		updateEntity.setId(id);
		updateEntity.setState(IOTServerNodeEnum.State.Usable.index());

		try {
			return dao.updateNotNull(updateEntity) > 0;
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		}

		return false;
	}

	public boolean close(Long id) throws LogicException {
		IOTServerNode iotServerNode = getById(id);
		if(iotServerNode == null){
			throw new LogicException("未找到IOT节点");
		}
		if(IOTServerNodeEnum.State.Unusable.index().equals(iotServerNode)){
			return true;
		}
		IOTServerNode updateEntity = new IOTServerNode();
		updateEntity.setId(id);
		updateEntity.setState(IOTServerNodeEnum.State.Unusable.index());

		try {
			return dao.updateNotNull(updateEntity) > 0;
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		}

		return false;
	}

	public boolean deleteById(Long id) {
		try {
			return dao.deleteById(id) > 0;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
}
